﻿using Mapster;
using SqlSugar;
using System.Dynamic;
using System.Text.Json;
using Zhp.Common.Helper;
using Zhp.Entity.Design;
using Zhp.IService.Design;
using Zhp.Model.Common;
using Zhp.Model.Design;
using Zhp.SqlSugar.Entity;
using Zhp.SqlSugar.Repository;

namespace Zhp.Service.Design
{
    public class DesignInstanceService : IDesignInstanceService
    {
        private ISqlSugarClient _sugarClient;
        private IBaseRepository<DesignList> _designListRep;
        private IBaseRepository<DesignForm> _designFormRep;
        private IDesignFormService _designFormService;
        private IDesignTableService _designTableService;
        public DesignInstanceService(
            ISqlSugarClient sugarClient,
            IBaseRepository<DesignList> designListRep,
            IBaseRepository<DesignForm> designFormRep,
            IDesignFormService designFormService,
            IDesignTableService designTableService) 
        {
            _sugarClient = sugarClient;
            _designListRep = designListRep;
            _designFormRep = designFormRep;
            _designFormService = designFormService;
            _designTableService = designTableService;
        }

        /// <summary>
        /// 查询配置信息
        /// </summary>
        /// <param name="listId"></param>
        /// <returns></returns>
        public async Task<DesignInstanceModel> QueryConfig(long listId)
        {
            var list = await _designListRep.GetByIdAsync(listId);
            var form = await _designFormRep.GetByIdAsync(list.FormId);

            var result = list.Adapt<DesignInstanceModel>();

            result.FormSetting = form.Adapt<DesignInstanceFormSetting>();

            return result;
        }

        public async Task<List<ExpandoObject>> Query(DesignInstanceQuery query)
        {
            var list = await _designListRep.GetByIdAsync(query.ListId);
            var form = await _designFormRep.GetByIdAsync(list.FormId);

            RefAsync<int> total = 0;

            var type = _designTableService.GetDynamicType(form.SourceCode);

            var orderList = await OrderByModels(form.SourceCode, query.Sorts);

            var where = CreateConditional(query.Query);
            
            var data = await _sugarClient.QueryableByObject(type, form.SourceCode).Where(where).OrderBy(orderList).ToPageListAsync(query.PageIndex, query.PageSize, total);
            
            query.TotalCount = total;

            // 这里转为ExpandoObject（相当于Dictionary）类型序列化时会保持原样输出
            return data.Adapt<List<ExpandoObject>>();
        }

        /// <summary>
        /// 保存实例数据
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public async Task<bool> Create(DesignInstanceEdit p)
        {
            var form = await _designFormRep.GetByIdAsync(p.FormId);

            var dict = await ConvetFormData(form, p.FormData);

            var type = _designTableService.GetDynamicType(form.SourceCode);
            var value = _sugarClient.DynamicBuilder().CreateObjectByType(type, dict);
            var result = await _sugarClient.InsertableByObject(value).ExecuteCommandAsync();

            return result > 0 ? true : false;
        }


        /// <summary>
        /// 修改实例数据
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public async Task<bool> Update(DesignInstanceEdit p)
        {
            var form = await _designFormRep.GetByIdAsync(p.FormId);

            var dict = await ConvetFormData(form, p.FormData);

            var type = _designTableService.GetDynamicType(form.SourceCode);
            var value = _sugarClient.DynamicBuilder().CreateObjectByType(type, dict);

            var result = await _sugarClient.UpdateableByObject(value).ExecuteCommandAsync();

            return result > 0 ? true : false;
        }

        public async Task<bool> Delete(long formId, long id)
        {
            var form = await _designFormRep.GetByIdAsync(formId);
            var type = _designTableService.GetDynamicType(form.SourceCode);
            var data = await _sugarClient.QueryableByObject(type, form.SourceCode).InSingleAsync(id);

            (data as IRootEntity).IsDeleted = true;

            var result = await _sugarClient.UpdateableByObject(data).ExecuteCommandAsync();

            return result > 0 ? true : false;
        }

        public async Task<ExpandoObject> Details(long formId, long id)
        {
            var form = await _designFormRep.GetByIdAsync(formId);
            var type = _designTableService.GetDynamicType(form.SourceCode);
            var result = await _sugarClient.QueryableByObject(type, form.SourceCode).InSingleAsync(id);
            // 这里转为ExpandoObject（相当于Dictionary）类型序列化时会保持原样输出
            var data = result.Adapt<ExpandoObject>();
            
            return data;
        }

        /// <summary>
        /// 表单数据处理
        /// </summary>
        /// <param name="form"></param>
        /// <param name="formData"></param>
        /// <returns></returns>
        private async Task<Dictionary<string, object>> ConvetFormData(DesignForm form, string formData)
        {
            var dict = formData.ToObject<Dictionary<string, object>>();

            var fieldList = await _designFormService.GetFormField(form.FormItemList);

            // 数组，对象，类型值序列化会有换行符，特殊处理
            foreach (var field in dict)
            {
                var fieldConfig = fieldList.FirstOrDefault(x => x.Field == field.Key);
                if (fieldConfig != null && fieldConfig.DataType == "array")
                {
                    dict[field.Key] = field.Value.ToJson();
                }
            }

            // 移除没用的相关字段
            RemoveExtraField(dict);

            return dict;
        }

        /// <summary>
        /// 移除没用的相关字段：IsDeleted，InsertExtraEntity，UpdateExtraEntity，DeleteExtraEntity
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private void RemoveExtraField(Dictionary<string, object> data)
        {
            var props = typeof(RootEntity).GetProperties().Select(x => x.Name);

            foreach (var item in props)
            {
                data.Remove(item, out object _);
            }
        }

        /// <summary>
        /// 排序参数
        /// </summary>
        /// <param name="sorts"></param>
        /// <returns></returns>
        public async Task<List<OrderByModel>> OrderByModels(string sourceCode, SortParam[] sorts)
        {
            var orderList = new List<OrderByModel>();
            if (sorts != null)
            {
                var columnList = await _designTableService.QueryColumn(sourceCode);
                foreach (var item in sorts)
                {
                    if (!string.IsNullOrEmpty(item.Order))
                    {
                        // 防注入
                        if (columnList.Any(x => x.ColumnName == item.Field))
                        {
                            orderList.Add(new OrderByModel
                            {
                                FieldName = item.Field,
                                OrderByType = item.Order == "ascending" ? OrderByType.Asc : OrderByType.Desc
                            });
                        }
                    }
                }
            }

            return orderList;
        }

        /// <summary>
        /// 查询条件
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public List<IConditionalModel> CreateConditional(List<DesignQuerySearch> query)
        {
            //查询条件
            var cs = new List<IConditionalModel>();
            foreach (var item in query)
            {
                var cm = new ConditionalModel
                {
                    FieldName = item.FieldName
                };
                if (item.FieldValue is JsonElement jsonElement && jsonElement.ValueKind == JsonValueKind.Array)
                {
                    var stringArray = jsonElement.EnumerateArray().Select(element =>
                    {
                        // 确保元素是字符串类型（ValueKind.String）
                        if (element.ValueKind == JsonValueKind.String)
                        {
                            return element.GetString();
                        }
                        else
                        {
                            return null;
                        }
                    }).ToArray();
                    cm.FieldValue = string.Join(",", stringArray);
                    cm.ConditionalType = ConditionalType.InLike;
                }
                else
                {
                    cm.FieldValue = item.FieldValue?.ToString();
                    cm.ConditionalType = ConditionalType.Like;
                }
                if (!string.IsNullOrEmpty(cm.FieldValue))
                {
                    cs.Add(cm);
                }
            }
            return cs;
        }
    }
}
